#pragma one

#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <vector>
#define CAPDEFAULT 5

template<class T>
class RingQueue
{
public:
    RingQueue(int cap = CAPDEFAULT)
        :_cap(cap)
        ,_rq(cap)
        ,_p_step(0)
        ,_c_step(0)
    {
        pthread_mutex_init(&_p_lock,nullptr);
        pthread_mutex_init(&_c_lock,nullptr);
        sem_init(&_space_sem, 0, cap);
        sem_init(&_data_sem, 0, 0);
    }

    void EnQueue(const T& in)
    {
        sem_wait(&_space_sem);
        {
            pthread_mutex_lock(&_p_lock);
            _rq[_p_step++] = in;
            _p_step %= _cap;
            pthread_mutex_unlock(&_p_lock);
        }
        sem_post(&_data_sem);
    }

    void Pop(T* out)
    {
        sem_wait(&_data_sem);
        {
            pthread_mutex_lock(&_c_lock);
            *out = _rq[_c_step++];
            _c_step %= _cap;
            pthread_mutex_unlock(&_c_lock);
        }
        sem_post(&_space_sem);
    }

    ~RingQueue()
    {
        pthread_mutex_destroy(&_p_lock);
        pthread_mutex_destroy(&_c_lock);
        sem_destroy(&_space_sem);
        sem_destroy(&_data_sem);
    }
private:
    std::vector<T> _rq;
    int _cap;
    sem_t _space_sem;
    sem_t _data_sem;

    int _p_step;//生产者的位置
    int _c_step;

    pthread_mutex_t _p_lock;
    pthread_mutex_t _c_lock;
};